package com.sdgs.paas.sdk.core.log;

import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;

/**
 * 日志操作对象，所有微服务开发中的日志统一通过本对象输出
 *
 * @author wjj
 *
 */
public class PaasLogger {
	private static final String FQCN = PaasLogger.class.getName();
	private static ConcurrentHashMap<String, PaasLog4jLogger> loggers = new ConcurrentHashMap<>();
	private static PaasLog4jLoggerFactory paasLog4jLoggerFactory = new PaasLog4jLoggerFactory();
	private static PaasLogBuilder bulider;

	// /**
	// *
	// *
	// * 获得Logger
	// *
	// *
	// * @param clazz
	// * 日志发出的类
	// *
	// *
	// * @return Logger
	// *
	// */
	//
	// public static Logger get(Class<?> clazz) {
	//
	// return LoggerFactory.getLogger(clazz);
	//
	// }
	//
	// /**
	// *
	// *
	// * 获得Logger
	// *
	// *
	// * @param name
	// * 自定义的日志发出者名称
	// *
	// *
	// * @return Logger
	// *
	// */
	//
	// public static Logger get(String name) {
	//
	// return LoggerFactory.getLogger(name);
	//
	// }
	//
	// /**
	// *
	// *
	// * @return 获得日志，自动判定日志发出者
	// *
	// */
	//
	// public static Logger get() {
	// return getLoggerFromCache(3);
	//
	// }

	/**
	 *
	 * 
	 * @return 获得日志，自动判定日志发出者
	 * 
	 */
	private static Logger innerGet() {
		PaasLog4jLogger logger = null;
		StackTraceElement[] stackTrace = new Throwable().getStackTrace();
		for (int i = stackTrace.length - 1; i >= 0; i--) {
			String paaslogger = stackTrace[i].getClassName();
			if (paaslogger.contains(FQCN)) {
				String loggername = stackTrace[i + 1 == stackTrace.length ? i : i + 1].getClassName();
				logger = loggers.get(loggername);
				if (logger == null) {
					logger = paasLog4jLoggerFactory.getLogger(loggername);
					loggers.put(loggername, logger);
				}
			}

		}

		return logger;

	}

	/**
	 *
	 * 
	 * Trace等级日志，小于debug<br>
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void trace(String format, Object... arguments) {

		trace(innerGet(), format, arguments);

	}

	/**
	 *
	 * 
	 * Trace等级日志，小于Debug
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void trace(Logger log, String format, Object... arguments) {

		log.trace(buildLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Debug等级日志，小于Info<br>
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void debug(String format, Object... arguments) {

		debug(innerGet(), format, arguments);

	}

	/**
	 *
	 * 
	 * Debug等级日志，小于Info
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void debug(Logger log, String format, Object... arguments) {

		log.debug(buildLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Info等级日志，小于Warn<br>
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void info(String format, Object... arguments) {

		info(innerGet(), format, arguments);

	}

	/**
	 *
	 * 
	 * Info等级日志，小于Warn
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void info(Logger log, String format, Object... arguments) {

		log.info(buildLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Warn等级日志，小于Error<br>
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void warn(String format, Object... arguments) {

		warn(innerGet(), format, arguments);

	}

	/**
	 *
	 * 
	 * Warn等级日志，小于Error
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void warn(Logger log, String format, Object... arguments) {

		log.warn(buildLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Warn等级日志，小于Error<br>
	 *
	 *
	 * 
	 * @param e
	 *            需在日志中堆栈打印的异常
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void warn(Throwable e, String format, Object... arguments) {

		warn(innerGet(), e, format(format, arguments));

	}

	/**
	 *
	 * 
	 * Warn等级日志，小于Error
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param e
	 *            需在日志中堆栈打印的异常
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void warn(Logger log, Throwable e, String format, Object... arguments) {

		log.warn(buildLog(format(format, arguments)), e);

	}

	/**
	 *
	 * 
	 * Error等级日志<br>
	 *
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void error(String format, Object... arguments) {

		error(innerGet(), format, arguments);

	}

	/**
	 *
	 * 
	 * Error等级日志<br>
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void error(Logger log, String format, Object... arguments) {

		log.error(buildLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Error等级日志<br>
	 *
	 * 
	 *
	 * 
	 * @param e
	 *            需在日志中堆栈打印的异常
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	public static void error(Throwable e, String format, Object... arguments) {

		error(innerGet(), e, format(format, arguments));

	}

	public static void metricInfo(String format, Object... arguments) {

		info(buildMetricLog(format), arguments);

	}

	public static void metricError(Throwable e, String format, Object... arguments) {

		error(e, buildMetricLog(format), arguments);

	}

	/**
	 *
	 * 
	 * Error等级日志<br>
	 *
	 *
	 * 
	 * @param log
	 *            日志对象
	 *
	 * 
	 * @param e
	 *            需在日志中堆栈打印的异常
	 *
	 * 
	 * @param format
	 *            格式文本，{} 代表变量
	 *
	 * 
	 * @param arguments
	 *            变量对应的参数
	 * 
	 */

	private static void error(Logger log, Throwable e, String format, Object... arguments) {

		log.error(buildLog(format(format, arguments)), e);

	}

	/**
	 *
	 * 
	 * 格式化文本
	 *
	 * 
	 * @param template
	 *            文本模板，被替换的部分用 {} 表示
	 *
	 * 
	 * @param values
	 *            参数值
	 *
	 * 
	 * @return 格式化后的文本
	 * 
	 */

	private static String format(String template, Object... values) {
		//如果没有替换值，就直接返回template
		if(values.length>0){
			return String.format(template.replace("{}", "%s"), values);
		}

		return template;

	}

	private static String buildLog(String content) {

		return (bulider = bulider == null ? new PaasLogBuilder() : bulider).build(content);

	}

	private static String buildMetricLog(String content) {

		return (bulider = bulider == null ? new PaasLogBuilder() : bulider).addMetricPrefix(content);

	}

	public static PaasLogBuilder getBulider() {
		return bulider;
	}

	public static void setBulider(PaasLogBuilder bulider) {
		PaasLogger.bulider = bulider;
	}

	public static void main(String[] args) {

		PaasLogger.metricError(new Throwable("fdsafa"), "aa:{}{}", "fdasfda{}fdsafa{}sdfd","{fsda}{}df");
	}

}
